home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / MACUNZIP / UNZIP.C < prev    next >
Text File  |  1991-08-16  |  42KB  |  1,693 lines

  1. /*
  2.  
  3. UnZip for the Macintosh
  4.  
  5. John Eng    July 1991
  6.  
  7. Based on the TURBO C Version 2.0.1 for the IBM by Samuel H. Smith as
  8. modified by George M. Sipe for "portability" to UNIX, Microsoft C for
  9. the IBM, and other machines.
  10.  
  11. This program unpacks .ZIP files, a packing format that is used on IBM
  12. systems.  On non-IBM systems, this program may be used to unpack text
  13. files and certain standard data (e.g., MIDI) files.
  14.  
  15. Several modifications of the "portable" Smith/Sipe source code were
  16. necessary to enable compilation on a Macintosh with the Lightspeed C
  17. v2.01 compiler.  All modifications for the Macintosh are initialled
  18. "J.E." with explanations in this source file; nothing from the original
  19. Smith/Sipe source file was deleted.  Two additional files, MacUnZip.h
  20. and MacUnZip.c, were created to compensate for non-portable code,
  21. libraries, and header files in the Smith/Sipe source as well as for
  22. idiosyncrasies and bugs of Lightspeed C v2.01. The latter may not be
  23. present in more recent versions of Lightspeed C.  I have minimized my
  24. modifications to the code and have hopefully enhanced its portability.
  25.  
  26. Please include these comments when uploading onto other computer
  27. services to assist any subsequent efforts to port this code.  */
  28.  
  29. #include "MacUnZip.h"    /* J.E., Special header file for the Macintosh */
  30.  
  31. /*
  32.  * Copyright 1989 Samuel H. Smith;  All rights reserved
  33.  *
  34.  * Do not distribute modified versions without my permission.
  35.  * Do not remove or alter this notice or any other copyright notice.
  36.  * If you use this in your own program you must distribute source code.
  37.  * Do not use any of this in a commercial product.
  38.  *
  39.  */
  40.  
  41. /*
  42.  * UnZip - A simple zipfile extract utility
  43.  *
  44.  * To compile:
  45.  *      tcc -B -O -Z -G -mc unzip.c    ;turbo C 2.0, compact model
  46.  *    cl /O /AC /G0 /W3 -c unzip.    ;msc 5.1, compact model
  47.  *    cc -O -DOLDC -Dunix {-DHIGH_LOW} {-DSHORTC} -c unzip.c    ;unix pcc
  48.  *
  49.  * Port to Unix and MSC (i.e. "portable version") by George M. Sipe
  50.  * (rebel!george).
  51.  *
  52.  */
  53.  
  54. #define VERSION  \
  55.     "UnZip:  Zipfile Extract v2.0.1 of 09-16-89;  (C) 1989 Samuel H. Smith"
  56.  
  57. #ifdef    SHORTC
  58. #define    compressed_size        cmpr_sz
  59. #define    extract_zipfile        ext_zip
  60. #define    filename        fn
  61. #define    follower        flwr
  62. #define    hsize_array_byte    hsz_a_byte
  63. #define    last_mod_file_date    mod_fdate
  64. #define    lit_tree_present    lt_present
  65. #define    maxcodemax        mx_cd_mx
  66. #define    number_disk_with_start_central_directory ndwsc
  67. #define    process_central_file_header pcfhdr
  68. #define    process_end_central_dir    pecdir
  69. #define    process_headers        proc_hdrs
  70. #define    total_entries_central_dir tecdir
  71. #define    version_made_by        v_made_by
  72. #define    LoadTrees        LdTrees
  73. #endif    /* SHORTC */
  74.  
  75. typedef unsigned char byte;    /* code assumes UNSIGNED bytes */
  76. typedef long longint;        /* sizeof must be 4 bytes */
  77. typedef unsigned short word;    /* sizeof must be 2 bytes */
  78. typedef char boolean;
  79.  
  80. #define STRSIZ 256
  81.  
  82. #include <stdio.h>
  83.  /* this is your standard header for all C compiles */
  84.  
  85. #ifndef    OLDC
  86. #include <stdlib.h>
  87.  /* this include defines various standard library prototypes */
  88. #define    VOIDARG    void        /* function definitions support (void) */
  89. #else
  90. #include <ctype.h>
  91. #define    VOIDARG            /* function definitions support () only */
  92. #endif    /* OLDC */
  93.  
  94.  
  95. /*
  96.  * SEE HOST OPERATING SYSTEM SPECIFICS SECTION STARTING NEAR LINE 180
  97.  *
  98.  */
  99.  
  100.  
  101. /* ----------------------------------------------------------- */
  102. /*
  103.  * Zipfile layout declarations
  104.  *
  105.  */
  106.  
  107. typedef longint signature_type;
  108.  
  109.  
  110. #define LOCAL_FILE_HEADER_SIGNATURE  0x04034b50L
  111.  
  112.  
  113. typedef struct local_file_header {
  114.     word version_needed_to_extract;
  115.         word general_purpose_bit_flag;
  116.     word compression_method;
  117.     word last_mod_file_time;
  118.     word last_mod_file_date;
  119.     longint crc32;
  120.     longint compressed_size;
  121.         longint uncompressed_size;
  122.     word filename_length;
  123.     word extra_field_length;
  124. } local_file_header;
  125.  
  126.  
  127. #define CENTRAL_FILE_HEADER_SIGNATURE  0x02014b50L
  128.  
  129.  
  130. typedef struct central_directory_file_header {
  131.     word version_made_by;
  132.     word version_needed_to_extract;
  133.     word general_purpose_bit_flag;
  134.     word compression_method;
  135.     word last_mod_file_time;
  136.     word last_mod_file_date;
  137.     longint crc32;
  138.     longint compressed_size;
  139.     longint uncompressed_size;
  140.     word filename_length;
  141.     word extra_field_length;
  142.     word file_comment_length;
  143.     word disk_number_start;
  144.     word internal_file_attributes;
  145.     longint external_file_attributes;
  146.     longint relative_offset_local_header;
  147. } central_directory_file_header;
  148.  
  149.  
  150. #define END_CENTRAL_DIR_SIGNATURE  0x06054b50L
  151.  
  152.  
  153. typedef struct end_central_dir_record {
  154.     word number_this_disk;
  155. #ifndef    TURBOC
  156.     word num_disk_with_start_cent_dir;
  157.     word tot_ents_cent_dir_on_this_disk;
  158. #else
  159.     word number_disk_with_start_central_directory;
  160.     word total_entries_central_dir_on_this_disk;
  161. #endif    /* TURBOC */
  162.     word total_entries_central_dir;
  163.     longint size_central_directory;
  164.     longint offset_start_central_directory;
  165.     word zipfile_comment_length;
  166. } end_central_dir_record;
  167.  
  168.  
  169.  
  170. /* ----------------------------------------------------------- */
  171. /*
  172.  * input file variables
  173.  *
  174.  */
  175.  
  176. #define INBUFSIZ 0x2000
  177. byte *inbuf;            /* input file buffer - any size is legal */
  178. byte *inptr;
  179.  
  180. int incnt;
  181. unsigned bitbuf;
  182. int bits_left;
  183. boolean zipeof;
  184.  
  185. int zipfd;
  186. char zipfn[STRSIZ];
  187. local_file_header lrec;
  188.  
  189. #ifdef    HIGH_LOW
  190. int w0, w1;            /* word translation indices */
  191. int li0, li1, li2, li3;        /* long int translation indices */
  192. #endif    /* HIGH_LOW */
  193.  
  194.  
  195. /* ----------------------------------------------------------- */
  196. /*
  197.  * output stream variables
  198.  *
  199.  */
  200.  
  201. #define OUTBUFSIZ 0x2000        /* must be 0x2000 or larger for unImplode */
  202. byte *outbuf;                   /* buffer for rle look-back */
  203. byte *outptr;
  204.  
  205. longint outpos;            /* absolute position in outfile */
  206. int outcnt;            /* current position in outbuf */
  207.  
  208. int outfd;
  209. char filename[STRSIZ];
  210. char extra[STRSIZ];
  211.  
  212. #define DLE 144
  213.  
  214.  
  215. /* ----------------------------------------------------------- */
  216. /*
  217.  * shrink/reduce working storage
  218.  *
  219.  */
  220.  
  221. int factor;
  222. byte followers[256][64];
  223. byte Slen[256];
  224.  
  225. #define max_bits 13
  226. #define init_bits 9
  227. #define hsize 8192
  228. #define first_ent 257
  229. #define clear 256
  230.  
  231. typedef int hsize_array_integer[hsize+1];
  232. typedef byte hsize_array_byte[hsize+1];
  233.  
  234. /*hsize_array_integer prefix_of;*/    /* J.E., See "MacUnZip.h" */
  235. /*hsize_array_byte suffix_of;*/       /* J.E. */
  236. /*hsize_array_byte stack;*/           /* J.E. */
  237.  
  238. int codesize;
  239. int maxcode;
  240. int free_ent;
  241. int maxcodemax;
  242. int offset;
  243. int sizex;
  244.  
  245.  
  246.  
  247. /* ============================================================= */
  248. /*
  249.  * Host operating system details
  250.  *
  251.  */
  252.  
  253. /*#include <string.h>*/    /* J.E., Non-portable header file */
  254. #include <strings.h>       /* J.E. */
  255.  /* this include defines strcpy, strcmp, etc. */
  256.  
  257. #ifndef    TURBOC
  258. /*#include <sys/types.h>*/     /* J.E., Non-portable header file */
  259. #include <types.h>             /* J.E. */
  260.  /*
  261.   * this include file defines
  262.   *        dev_t (* device type *)
  263.   * as used in the sys/utime.h and sys/stat.h header files below
  264.   */
  265.  
  266. #ifndef    OLDC
  267. #include <sys/utime.h>
  268.  /*
  269.   * this include file defines
  270.   *        struct utimbuf (* utime buffer structure *)
  271.   *        utime()        (* utime function *)
  272.   * as used in the set_file_time() function defined below
  273.   */
  274. #endif    /* !OLDC */
  275. #endif    /* !TURBOC */
  276.  
  277. #ifndef    TURBOC
  278. #include <time.h>
  279. struct ftime {
  280.     unsigned ft_tsec: 5;    /* two seconds */
  281.     unsigned ft_min: 6;    /* minutes */
  282.     unsigned ft_hour: 5;    /* hours */
  283.     unsigned ft_day: 5;    /* days */
  284.     unsigned ft_month: 4;    /* months */
  285.     unsigned ft_year: 7;    /* years  - 1980 */
  286. };
  287. #endif    /* TURBOC */
  288. #ifndef    OLDC
  289. #include <io.h>
  290. #else
  291. /*#include <sys/file.h>*/    /* J.E., Non-portable header file */
  292. #ifdef    L_SET
  293. #define    SEEK_SET    L_SET
  294. #else
  295. #define    SEEK_SET    0
  296. #endif    /* L_SET */
  297. #endif    /* OLDC */
  298.  /*
  299.   * this include file defines
  300.   *             struct ftime ...        (* file time/date stamp info *)
  301.   *             int setftime (int handle, struct ftime *ftimep);
  302.   *             #define SEEK_CUR  1     (* lseek() modes *)
  303.   *             #define SEEK_END  2
  304.   *             #define SEEK_SET  0
  305.   */
  306.  
  307. /*#include <fcntl.h>*/    /* J.E., Non-portable header file */
  308. #ifndef    O_BINARY
  309. #define    O_BINARY    0
  310. #endif    /* O_BINARY */
  311.  /*
  312.   * this include file defines
  313.   *             #define O_BINARY 0x8000  (* no cr-lf translation *)
  314.   * as used in the open() standard function
  315.   */
  316.  
  317. /*#include <sys/stat.h>*/    /* J.E., Non-portable header file */
  318.  /*
  319.   * this include file defines
  320.   *             #define S_IREAD 0x0100  (* owner may read *)
  321.   *             #define S_IWRITE 0x0080 (* owner may write *)
  322.   * as used in the creat() standard function
  323.   */
  324.  
  325. /* #undef HIGH_LOW - define externally */
  326.  /*
  327.   * change 'undef' to 'define' if your machine stores high order bytes in
  328.   * lower addresses.
  329.   */
  330.  
  331. void set_file_time(VOIDARG)
  332.  /*
  333.   * set the output file date/time stamp according to information from the
  334.   * zipfile directory record for this file 
  335.   */
  336. {
  337.     union {
  338.                 struct ftime ft;        /* system file time record */
  339.         struct {
  340.                         word ztime;     /* date and time words */
  341.                         word zdate;     /* .. same format as in .ZIP file */
  342.         } zt;
  343.     } td;
  344.  
  345.     /*
  346.      * set output file date and time - this is optional and can be
  347.      * deleted if your compiler does not easily support setftime() 
  348.      */
  349. #ifdef    TURBOC
  350.     td.zt.ztime = lrec.last_mod_file_time;
  351.     td.zt.zdate = lrec.last_mod_file_date;
  352.  
  353.     setftime(outfd, &td.ft);
  354. #else
  355.  
  356. #define leap(y)     (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
  357. #define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
  358.  
  359.     static char month_lengths[] =
  360.         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  361.     int day_of_year, year;
  362. #ifndef    OLDC
  363.     struct utimbuf times;
  364. #else
  365.     struct utimbuf {
  366.         time_t actime;        /* file accessed time */
  367.         time_t modtime;        /* file updated time */
  368.     } times;
  369. #endif    /* OLDC */
  370.  
  371.     /*
  372.      * this is the standard Unix implementation (also fully
  373.      * compatible with MSC)
  374.      */
  375.  
  376.     close(outfd);
  377.     td.zt.ztime = lrec.last_mod_file_time;
  378.     td.zt.zdate = lrec.last_mod_file_date;
  379.     year = td.ft.ft_year + 1980;
  380.     if (td.ft.ft_month < 1 || td.ft.ft_month > 12 || td.ft.ft_day < 1
  381.         || td.ft.ft_day > month_lengths[td.ft.ft_month-1]
  382.         && !(td.ft.ft_month == 2 && td.ft.ft_day == 29 && leap (year))
  383.         || td.ft.ft_hour > 23 || td.ft.ft_min > 59 ||
  384.         td.ft.ft_tsec*2 > 59)
  385.         return;
  386.     day_of_year = td.ft.ft_day - 1;
  387.     if (td.ft.ft_month > 2 && leap(year)) ++day_of_year;
  388.     while (--td.ft.ft_month > 0)
  389.         day_of_year += month_lengths[td.ft.ft_month - 1];
  390.     times.modtime = (86400 * (long)(day_of_year + 365 * (year - 1970) 
  391.         + nleap (year)) + 3600 * (td.ft.ft_hour-1) + 60 * td.ft.ft_min
  392.         + td.ft.ft_tsec*2);
  393. #ifdef    HAVE_TZ
  394.     tzset();
  395.     times.modtime += timezone;
  396. #endif    /* HAVE_TZ */
  397.     times.actime = times.modtime;
  398.     utime(filename, ×);
  399. #endif    /* !TURBOC */
  400. }
  401.  
  402.  
  403. int create_output_file(VOIDARG)
  404.  /* return non-0 if creat failed */
  405. {
  406.     /* create the output file with READ and WRITE permissions */
  407.     outfd = creat(filename, S_IWRITE | S_IREAD | S_IREAD >> 3
  408.             | S_IREAD >> 6);
  409.     if (outfd < 1) {
  410.         printf("Can't create output: %s\n", filename);
  411.         return 1;
  412.     }
  413.  
  414.     /*
  415.      * close the newly created file and reopen it in BINARY mode to
  416.      * disable all CR/LF translations 
  417.      */
  418.     close(outfd);
  419.     outfd = open(filename, O_RDWR | O_BINARY);
  420.  
  421.     /* write a single byte at EOF to pre-allocate the file */
  422. #ifdef    tx
  423.     fsetsize(outfd, lrec.uncompressed_size);
  424. #endif    /* tx */
  425.         lseek(outfd, lrec.uncompressed_size - 1L, SEEK_SET);
  426.     write(outfd, "?", 1);
  427.     lseek(outfd, 0L, SEEK_SET);
  428.     return 0;
  429. }
  430.  
  431.  
  432. int open_input_file(VOIDARG)
  433.  /* return non-0 if creat failed */
  434. {
  435.     /*
  436.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  437.      * translation, which would corrupt the bitstreams 
  438.      */
  439.  
  440.     zipfd = open(zipfn, O_RDONLY | O_BINARY);
  441.     if (zipfd < 1) {
  442.         printf("Can't open input file: %s\n", zipfn);
  443.         return (1);
  444.     }
  445.     return 0;
  446. }
  447.  
  448.  
  449. #ifdef HIGH_LOW
  450.  
  451. #ifndef    OLDC
  452. void swap_bytes(word *wordp)
  453. #else
  454. void swap_bytes(wordp)
  455. word *wordp;
  456. #endif    /* OLDC */
  457.  /* convert intel style 'short int' variable to host format */
  458. {
  459.     char *charp = (char *) wordp;
  460.     char temp[2];
  461.  
  462.     temp[0] = charp[w0];
  463.     temp[1] = charp[w1];
  464.     charp[0] = temp[0];
  465.     charp[1] = temp[1];
  466. }
  467.  
  468. #ifndef    OLDC
  469. void swap_lbytes(longint *longp)
  470. #else
  471. void swap_lbytes(longp)
  472. longint *longp;
  473. #endif    /* OLDC */
  474.  /* convert intel style 'long' variable to host format */
  475. {
  476.     char *charp = (char *) longp;
  477.     char temp[4];
  478.  
  479.     temp[0] = charp[li0];
  480.     temp[1] = charp[li1];
  481.     temp[2] = charp[li2];
  482.     temp[3] = charp[li3];
  483.     charp[0] = temp[0];
  484.     charp[1] = temp[1];
  485.     charp[2] = temp[2];
  486.     charp[3] = temp[3];
  487. }
  488.  
  489. #endif    /* HIGH_LOW */
  490.  
  491.  
  492.  
  493. /* ============================================================= */
  494.  
  495. int FillBuffer(VOIDARG)
  496.  /* fill input buffer if possible */
  497. {
  498.     int readsize;
  499.  
  500.         if (lrec.compressed_size <= 0)
  501.         return incnt = 0;
  502.  
  503.         if (lrec.compressed_size > INBUFSIZ)
  504.         readsize = INBUFSIZ;
  505.     else
  506.                 readsize = (int) lrec.compressed_size;
  507.     incnt = read(zipfd, inbuf, readsize);
  508.  
  509.         lrec.compressed_size -= incnt;
  510.     inptr = inbuf;
  511.     return incnt--;
  512. }
  513.  
  514. #ifndef    OLDC
  515. int ReadByte(unsigned *x)
  516. #else
  517. int ReadByte(x)
  518. unsigned *x;
  519. #endif    /* OLDC */
  520.  /* read a byte; return 8 if byte available, 0 if not */
  521. {
  522.     if (incnt-- == 0)
  523.         if (FillBuffer() == 0)
  524.             return 0;
  525.  
  526.     *x = *inptr++;
  527.     return 8;
  528. }
  529.  
  530.  
  531. /* ------------------------------------------------------------- */
  532. static unsigned mask_bits[] =
  533.         {0,     0x0001, 0x0003, 0x0007, 0x000f,
  534.                 0x001f, 0x003f, 0x007f, 0x00ff,
  535.                 0x01ff, 0x03ff, 0x07ff, 0x0fff,
  536.                 0x1fff, 0x3fff, 0x7fff, 0xffff
  537.         };
  538.  
  539.  
  540. #ifndef    OLDC
  541. int FillBitBuffer(register int bits)
  542. #else
  543. int FillBitBuffer(bits)
  544. register int bits;
  545. #endif    /* OLDC */
  546.  /* read a byte; return 8 if byte available, 0 if not */
  547. {
  548.     /* get the bits that are left and read the next word */
  549.     unsigned temp;
  550.         register int result = bitbuf;
  551.     int sbits = bits_left;
  552.     bits -= bits_left;
  553.  
  554.     /* read next word of input */
  555.     bits_left = ReadByte(&bitbuf);
  556.     bits_left += ReadByte(&temp);
  557.     bitbuf |= (temp << 8);
  558.     if (bits_left == 0)
  559.         zipeof = 1;
  560.  
  561.     /* get the remaining bits */
  562.         result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
  563.         bitbuf >>= bits;
  564.         bits_left -= bits;
  565.         return result;
  566. }
  567.  
  568. #define READBIT(nbits,zdest,ztype) \
  569.     { if (nbits <= bits_left) \
  570.         { zdest = ztype(bitbuf & mask_bits[nbits]); \
  571.         bitbuf >>= nbits; bits_left -= nbits; } \
  572.     else zdest = ztype(FillBitBuffer(nbits));}
  573.  
  574. /*
  575.  * macro READBIT(nbits,zdest,ztype)
  576.  *  {
  577.  *      if (nbits <= bits_left) {
  578.  *          zdest = ztype(bitbuf & mask_bits[nbits]);
  579.  *          bitbuf >>= nbits;
  580.  *          bits_left -= nbits;
  581.  *      } else
  582.  *          zdest = ztype(FillBitBuffer(nbits));
  583.  *  }
  584.  *
  585.  */
  586.  
  587.  
  588. /* ------------------------------------------------------------- */
  589.  
  590. #include "crc32.h"
  591.  
  592.  
  593. /* ------------------------------------------------------------- */
  594.  
  595. void FlushOutput(VOIDARG)
  596.  /* flush contents of output buffer */
  597. {
  598.     UpdateCRC(outbuf, outcnt);
  599.     write(outfd, outbuf, outcnt);
  600.     outpos += outcnt;
  601.     outcnt = 0;
  602.     outptr = outbuf;
  603. }
  604.  
  605. #define OUTB(intc) { *outptr++=intc; if (++outcnt==OUTBUFSIZ) FlushOutput(); }
  606.  
  607. /*
  608.  *  macro OUTB(intc)
  609.  *  {
  610.  *      *outptr++=intc;
  611.  *      if (++outcnt==OUTBUFSIZ)
  612.  *          FlushOutput();
  613.  *  }
  614.  *
  615.  */
  616.  
  617.  
  618. /* ----------------------------------------------------------- */
  619.  
  620. void LoadFollowers(VOIDARG)
  621. {
  622.         register int x;
  623.         register int i;
  624.  
  625.     for (x = 255; x >= 0; x--) {
  626.                 READBIT(6,Slen[x],(byte));
  627.         for (i = 0; i < Slen[x]; i++) {
  628.                         READBIT(8,followers[x][i],(byte));
  629.         }
  630.     }
  631. }
  632.  
  633.  
  634. /* ----------------------------------------------------------- */
  635. /*
  636.  * The Reducing algorithm is actually a combination of two
  637.  * distinct algorithms.  The first algorithm compresses repeated
  638.  * byte sequences, and the second algorithm takes the compressed
  639.  * stream from the first algorithm and applies a probabilistic
  640.  * compression method.
  641.  */
  642.  
  643. int L_table[] = {0, 0x7f, 0x3f, 0x1f, 0x0f};
  644.  
  645. int D_shift[] = {0, 0x07, 0x06, 0x05, 0x04};
  646. int D_mask[]  = {0, 0x01, 0x03, 0x07, 0x0f};
  647.  
  648. int B_table[] = {8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
  649.          5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
  650.          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  651.          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
  652.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  653.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  654.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  655.          7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  656.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  657.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  658.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  659.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  660.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  661.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  662.          8, 8, 8, 8};
  663.  
  664. /* ----------------------------------------------------------- */
  665.  
  666. void unReduce(VOIDARG)
  667.  /* expand probablisticly reduced data */
  668. {
  669.         register int lchar;
  670.         int nchar;
  671.         int ExState;
  672.         int V;
  673.         int Len;
  674.  
  675.         factor = lrec.compression_method - 1;
  676.     ExState = 0;
  677.     lchar = 0;
  678.     LoadFollowers();
  679.  
  680.         while (((outpos+outcnt) < lrec.uncompressed_size) && (!zipeof)) {
  681.         if (Slen[lchar] == 0)
  682.                         READBIT(8,nchar,(int))      /* ; */
  683.                 else
  684.         {
  685.                         READBIT(1,nchar,(int));
  686.                         if (nchar != 0)
  687.                                 READBIT(8,nchar,(int))      /* ; */
  688.                         else
  689.             {
  690.                                 int follower;
  691.                                 int bitsneeded = B_table[Slen[lchar]];
  692.                                 READBIT(bitsneeded,follower,(int));
  693.                                 nchar = followers[lchar][follower];
  694.             }
  695.         }
  696.  
  697.         /* expand the resulting byte */
  698.         switch (ExState) {
  699.  
  700.         case 0:
  701.                         if (nchar != DLE)
  702.                                 OUTB((byte) nchar) /*;*/
  703.             else
  704.                 ExState = 1;
  705.             break;
  706.  
  707.         case 1:
  708.                         if (nchar != 0) {
  709.                                 V = nchar;
  710.                 Len = V & L_table[factor];
  711.                 if (Len == L_table[factor])
  712.                     ExState = 2;
  713.                 else
  714.                     ExState = 3;
  715.             }
  716.             else {
  717.                                 OUTB(DLE);
  718.                 ExState = 0;
  719.             }
  720.             break;
  721.  
  722.                 case 2: {
  723.                                 Len += nchar;
  724.                 ExState = 3;
  725.             }
  726.             break;
  727.  
  728.                 case 3: {
  729.                 register int i = Len + 3;
  730.                 int offset = (((V >> D_shift[factor]) &
  731.                                           D_mask[factor]) << 8) + nchar + 1;
  732.                                 longint op = (outpos+outcnt) - offset;
  733.  
  734.                 /* special case- before start of file */
  735.                 while ((op < 0L) && (i > 0)) {
  736.                     OUTB(0);
  737.                     op++;
  738.                     i--;
  739.                 }
  740.  
  741.                 /* normal copy of data from output buffer */
  742.                 {
  743.                     register int ix = (int) (op % OUTBUFSIZ);
  744.  
  745.                                         /* do a block memory copy if possible */
  746.                                         if ( ((ix    +i) < OUTBUFSIZ) &&
  747.                                              ((outcnt+i) < OUTBUFSIZ) ) {
  748.                                                 memcpy(outptr,&outbuf[ix],i);
  749.                                                 outptr += i;
  750.                                                 outcnt += i;
  751.                                         }
  752.  
  753.                                         /* otherwise copy byte by byte */
  754.                                         else while (i--) {
  755.                                                 OUTB(outbuf[ix]);
  756.                                                 if (++ix >= OUTBUFSIZ)
  757.                                                         ix = 0;
  758.                                         }
  759.                                 }
  760.  
  761.                 ExState = 0;
  762.             }
  763.             break;
  764.         }
  765.  
  766.                 /* store character for next iteration */
  767.                 lchar = nchar;
  768.         }
  769. }
  770.  
  771.  
  772. /* ------------------------------------------------------------- */
  773. /*
  774.  * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
  775.  * with partial clearing.
  776.  *
  777.  */
  778.  
  779. void partial_clear(VOIDARG)
  780. {
  781.         register int pr;
  782.         register int cd;
  783.  
  784.     /* mark all nodes as potentially unused */
  785.     for (cd = first_ent; cd < free_ent; cd++)
  786.         prefix_of[cd] |= 0x8000;
  787.  
  788.     /* unmark those that are used by other nodes */
  789.     for (cd = first_ent; cd < free_ent; cd++) {
  790.         pr = prefix_of[cd] & 0x7fff;    /* reference to another node? */
  791.                 if (pr >= first_ent)            /* flag node as referenced */
  792.             prefix_of[pr] &= 0x7fff;
  793.     }
  794.  
  795.     /* clear the ones that are still marked */
  796.     for (cd = first_ent; cd < free_ent; cd++)
  797.         if ((prefix_of[cd] & 0x8000) != 0)
  798.             prefix_of[cd] = -1;
  799.  
  800.     /* find first cleared node as next free_ent */
  801.         cd = first_ent;
  802.         while ((cd < maxcodemax) && (prefix_of[cd] != -1))
  803.                 cd++;
  804.         free_ent = cd;
  805. }
  806.  
  807.  
  808. /* ------------------------------------------------------------- */
  809.  
  810. void unShrink(VOIDARG)
  811. {
  812. #define  GetCode(dest) READBIT(codesize,dest,(int))
  813.  
  814.     register int code;
  815.     register int stackp;
  816.     int finchar;
  817.     int oldcode;
  818.     int incode;
  819.  
  820.  
  821.     /* decompress the file */
  822.     maxcodemax = 1 << max_bits;
  823.     codesize = init_bits;
  824.     maxcode = (1 << codesize) - 1;
  825.     free_ent = first_ent;
  826.     offset = 0;
  827.     sizex = 0;
  828.  
  829.     for (code = maxcodemax; code > 255; code--)
  830.         prefix_of[code] = -1;
  831.  
  832.     for (code = 255; code >= 0; code--) {
  833.         prefix_of[code] = 0;
  834.         suffix_of[code] = (byte) code;
  835.     }
  836.  
  837.     GetCode(oldcode);
  838.     if (zipeof)
  839.         return;
  840.     finchar = oldcode;
  841.  
  842.         OUTB((byte) finchar);
  843.  
  844.         stackp = hsize;
  845.  
  846.     while (!zipeof) {
  847.         GetCode(code);
  848.         if (zipeof)
  849.             return;
  850.  
  851.         while (code == clear) {
  852.             GetCode(code);
  853.             switch (code) {
  854.  
  855.             case 1:{
  856.                     codesize++;
  857.                     if (codesize == max_bits)
  858.                         maxcode = maxcodemax;
  859.                     else
  860.                         maxcode = (1 << codesize) - 1;
  861.                 }
  862.                 break;
  863.  
  864.             case 2:
  865.                 partial_clear();
  866.                 break;
  867.             }
  868.  
  869.             GetCode(code);
  870.             if (zipeof)
  871.                 return;
  872.         }
  873.  
  874.  
  875.         /* special case for KwKwK string */
  876.         incode = code;
  877.         if (prefix_of[code] == -1) {
  878.                         stack[--stackp] = (byte) finchar;
  879.             code = oldcode;
  880.         }
  881.  
  882.  
  883.         /* generate output characters in reverse order */
  884.         while (code >= first_ent) {
  885.                         stack[--stackp] = suffix_of[code];
  886.             code = prefix_of[code];
  887.         }
  888.  
  889.         finchar = suffix_of[code];
  890.                 stack[--stackp] = (byte) finchar;
  891.  
  892.  
  893.                 /* and put them out in forward order, block copy */
  894.                 if ((hsize-stackp+outcnt) < OUTBUFSIZ) {
  895.                         memcpy(outptr,&stack[stackp],hsize-stackp);
  896.                         outptr += hsize-stackp;
  897.                         outcnt += hsize-stackp;
  898.                         stackp = hsize;
  899.                 }
  900.  
  901.                 /* output byte by byte if we can't go by blocks */
  902.                 else while (stackp < hsize)
  903.                         OUTB(stack[stackp++]);
  904.  
  905.  
  906.         /* generate new entry */
  907.         code = free_ent;
  908.         if (code < maxcodemax) {
  909.             prefix_of[code] = oldcode;
  910.             suffix_of[code] = (byte) finchar;
  911.  
  912.             do
  913.                 code++;
  914.             while ((code < maxcodemax) && (prefix_of[code] != -1));
  915.  
  916.             free_ent = code;
  917.         }
  918.  
  919.         /* remember previous code */
  920.         oldcode = incode;
  921.     }
  922.  
  923. }
  924.  
  925.  
  926. /* ------------------------------------------------------------- */ 
  927. /*
  928.  * Imploding
  929.  * ---------
  930.  *
  931.  * The Imploding algorithm is actually a combination of two distinct
  932.  * algorithms.  The first algorithm compresses repeated byte sequences
  933.  * using a sliding dictionary.  The second algorithm is used to compress
  934.  * the encoding of the sliding dictionary ouput, using multiple
  935.  * Shannon-Fano trees.
  936.  *
  937.  */ 
  938.  
  939. #define maxSF 256
  940.  
  941.    typedef struct sf_entry { 
  942.                  word         Code; 
  943.                  byte         Value; 
  944.                  byte         BitLength; 
  945.               } sf_entry; 
  946.  
  947.    typedef struct sf_tree {   /* a shannon-fano tree */ 
  948.       sf_entry     entry[maxSF];
  949.       int          entries;
  950.       int          MaxLength;
  951.    } sf_tree; 
  952.  
  953.    typedef sf_tree      *sf_treep; 
  954.  
  955.    sf_tree      lit_tree; 
  956.    sf_tree      length_tree; 
  957.    sf_tree      distance_tree; 
  958.    boolean      lit_tree_present; 
  959.    boolean      eightK_dictionary; 
  960.    int          minimum_match_length;
  961.    int          dict_bits;
  962.  
  963.  
  964. #ifndef    OLDC
  965. void SortLengths(sf_tree *tree)
  966. #else
  967. void SortLengths(tree)
  968. sf_tree *tree;
  969. #endif    /* OLDC */
  970.   /* Sort the Bit Lengths in ascending order, while retaining the order
  971.     of the original lengths stored in the file */ 
  972.    int          x;
  973.    int          gap;
  974.    sf_entry     t; 
  975.    boolean      noswaps;
  976.    int          a, b;
  977.  
  978.    gap = tree->entries / 2; 
  979.  
  980.    do { 
  981.       do { 
  982.          noswaps = 1;
  983.          for (x = 0; x <= (tree->entries - 1) - gap; x++) 
  984.          { 
  985.             a = tree->entry[x].BitLength; 
  986.             b = tree->entry[x + gap].BitLength; 
  987.             if ((a > b) || ((a == b) && (tree->entry[x].Value > tree->entry[x + gap].Value))) 
  988.             { 
  989.                t = tree->entry[x]; 
  990.                tree->entry[x] = tree->entry[x + gap]; 
  991.                tree->entry[x + gap] = t; 
  992.                noswaps = 0;
  993.             } 
  994.          } 
  995.       }  while (!noswaps);
  996.  
  997.       gap = gap / 2; 
  998.    }  while (gap > 0);
  999.  
  1000.  
  1001. /* ----------------------------------------------------------- */ 
  1002.  
  1003. #ifndef    OLDC
  1004. void ReadLengths(sf_tree *tree)
  1005. #else
  1006. void ReadLengths(tree)
  1007. sf_tree *tree;
  1008. #endif    /* OLDC */
  1009.    int          treeBytes;
  1010.    int          i;
  1011.    int          num, len;
  1012.  
  1013.   /* get number of bytes in compressed tree */
  1014.    READBIT(8,treeBytes,(int));
  1015.    treeBytes++; 
  1016.    i = 0; 
  1017.  
  1018.    tree->MaxLength = 0;
  1019.  
  1020.  /* High 4 bits: Number of values at this bit length + 1. (1 - 16)
  1021.     Low  4 bits: Bit Length needed to represent value + 1. (1 - 16) */
  1022.    while (treeBytes > 0)
  1023.    {
  1024.       READBIT(4,len,(int)); len++;
  1025.       READBIT(4,num,(int)); num++;
  1026.  
  1027.       while (num > 0)
  1028.       {
  1029.          if (len > tree->MaxLength)
  1030.             tree->MaxLength = len;
  1031.          tree->entry[i].BitLength = (byte) len;
  1032.          tree->entry[i].Value = (byte) i;
  1033.          i++;
  1034.          num--;
  1035.       }
  1036.  
  1037.       treeBytes--;
  1038.    } 
  1039.  
  1040.  
  1041. /* ----------------------------------------------------------- */ 
  1042.  
  1043. #ifndef    OLDC
  1044. void GenerateTrees(sf_tree *tree)
  1045. #else
  1046. void GenerateTrees(tree)
  1047. sf_tree *tree;
  1048. #endif    /* OLDC */
  1049.      /* Generate the Shannon-Fano trees */ 
  1050.    word         Code;
  1051.    int          CodeIncrement;
  1052.    int          LastBitLength;
  1053.    int          i;
  1054.  
  1055.  
  1056.    Code = 0;
  1057.    CodeIncrement = 0; 
  1058.    LastBitLength = 0; 
  1059.  
  1060.    i = tree->entries - 1;   /* either 255 or 63 */ 
  1061.    while (i >= 0) 
  1062.    { 
  1063.       Code += CodeIncrement; 
  1064.       if (tree->entry[i].BitLength != (byte) LastBitLength) 
  1065.       { 
  1066.          LastBitLength = tree->entry[i].BitLength; 
  1067.          CodeIncrement = 1 << (16 - LastBitLength); 
  1068.       } 
  1069.  
  1070.       tree->entry[i].Code = Code; 
  1071.       i--; 
  1072.    } 
  1073.  
  1074.  
  1075. /* ----------------------------------------------------------- */ 
  1076.  
  1077. #ifndef    OLDC
  1078. void ReverseBits(sf_tree *tree)
  1079. #else
  1080. void ReverseBits(tree)
  1081. sf_tree *tree;
  1082. #endif    /* OLDC */
  1083.  /* Reverse the order of all the bits in the above ShannonCode[]
  1084.     vector, so that the most significant bit becomes the least
  1085.     significant bit. For example, the value 0x1234 (hex) would become
  1086.     0x2C48 (hex). */ 
  1087.    int          i;
  1088.    word         mask;
  1089.    word         revb;
  1090.    word         v;
  1091.    word         o;
  1092.    int          b;
  1093.  
  1094.  
  1095.    for (i = 0; i <= tree->entries - 1; i++) 
  1096.    { 
  1097.         /* get original code */ 
  1098.       o = tree->entry[i].Code; 
  1099.  
  1100.         /* reverse each bit */ 
  1101.       mask = 0x0001;
  1102.       revb = 0x8000;
  1103.       v = 0;
  1104.       for (b = 0; b <= 15; b++) 
  1105.       { 
  1106.            /* if bit set in mask, then substitute reversed bit */ 
  1107.          if ((o & mask) != 0) 
  1108.             v = v | revb; 
  1109.  
  1110.            /* advance to next bit */ 
  1111.          revb = (revb >> 1);
  1112.          mask = (mask << 1);
  1113.       } 
  1114.  
  1115.         /* store reversed bits */ 
  1116.       tree->entry[i].Code = v; 
  1117.    } 
  1118.  
  1119.  
  1120. /* ----------------------------------------------------------- */ 
  1121.  
  1122. #ifndef    OLDC
  1123. void LoadTree(sf_tree *tree, int treesize)
  1124. #else
  1125. void LoadTree(tree, treesize)
  1126. sf_tree *tree;
  1127. int treesize;
  1128. #endif    /* OLDC */
  1129.      /* allocate and load a shannon-fano tree from the compressed file */ 
  1130.    tree->entries = treesize; 
  1131.    ReadLengths(tree); 
  1132.    SortLengths(tree); 
  1133.    GenerateTrees(tree); 
  1134.    ReverseBits(tree); 
  1135.  
  1136.  
  1137. /* ----------------------------------------------------------- */ 
  1138.  
  1139. #ifndef    OLDC
  1140. void LoadTrees(void)
  1141. #else
  1142. void LoadTrees()
  1143. #endif    /* OLDC */
  1144.    /* bit 1... */
  1145.    eightK_dictionary = (boolean) ((lrec.general_purpose_bit_flag & 0x02) != 0);
  1146.    /* bit 2... */
  1147.    lit_tree_present = (boolean) ((lrec.general_purpose_bit_flag & 0x04) != 0);
  1148.  
  1149.    if (eightK_dictionary) 
  1150.       dict_bits = 7;
  1151.    else 
  1152.       dict_bits = 6; 
  1153.  
  1154.    if (lit_tree_present) 
  1155.    { 
  1156.       minimum_match_length = 3; 
  1157.       LoadTree(&lit_tree,256); 
  1158.    } 
  1159.    else 
  1160.       minimum_match_length = 2; 
  1161.  
  1162.    LoadTree(&length_tree,64); 
  1163.    LoadTree(&distance_tree,64); 
  1164.  
  1165.  
  1166. /* ----------------------------------------------------------- */ 
  1167.  
  1168. #ifndef    OLDC
  1169. void ReadTree(sf_tree *tree, int *dest)
  1170. #else
  1171. void ReadTree(tree, dest)
  1172. sf_tree *tree;
  1173. int *dest;
  1174. #endif    /* OLDC */
  1175.      /* read next byte using a shannon-fano tree */ 
  1176.    int          bits = 0;
  1177.    word         cv = 0;
  1178.    int          cur = 0;
  1179.    int          b;
  1180.  
  1181.    *dest = -1;   /* in case of error */ 
  1182.  
  1183.    for (;;)
  1184.    { 
  1185.       READBIT(1,b,(int));
  1186.       cv = cv | (b << bits);
  1187.       bits++; 
  1188.  
  1189.       /* this is a very poor way of decoding shannon-fano.  two quicker
  1190.          methods come to mind:
  1191.             a) arrange the tree as a huffman-style binary tree with
  1192.                a "leaf" indicator at each node,
  1193.          and
  1194.             b) take advantage of the fact that s-f codes are at most 8
  1195.                bits long and alias unused codes for all bits following
  1196.                the "leaf" bit.
  1197.       */
  1198.  
  1199.       while (tree->entry[cur].BitLength < (byte) bits) 
  1200.       { 
  1201.          cur++; 
  1202.          if (cur >= tree->entries) 
  1203.             return; /* data error */
  1204.       } 
  1205.  
  1206.       while (tree->entry[cur].BitLength == (byte) bits) 
  1207.       { 
  1208.          if (tree->entry[cur].Code == cv) 
  1209.          { 
  1210.             *dest = tree->entry[cur].Value; 
  1211.             return; 
  1212.          } 
  1213.  
  1214.          cur++; 
  1215.          if (cur >= tree->entries) 
  1216.             return; /* data error */
  1217.       } 
  1218.    } 
  1219.  
  1220.  
  1221. /* ----------------------------------------------------------- */ 
  1222.  
  1223. #ifndef    OLDC
  1224. void unImplode(void)
  1225. #else
  1226. void unImplode()
  1227. #endif    /* OLDC */
  1228.      /* expand imploded data */ 
  1229.  
  1230.    int          lout;
  1231.    longint      op;
  1232.    int          Length;
  1233.    int          Distance;
  1234.  
  1235.    LoadTrees(); 
  1236.  
  1237.    while ((!zipeof) && ((outpos+outcnt) < lrec.uncompressed_size))
  1238.    { 
  1239.       READBIT(1,lout,(int));
  1240.  
  1241.       if (lout != 0)   /* encoded data is literal data */ 
  1242.       { 
  1243.          if (lit_tree_present)  /* use Literal Shannon-Fano tree */
  1244.             ReadTree(&lit_tree,&lout);
  1245.          else 
  1246.             READBIT(8,lout,(int));
  1247.  
  1248.          OUTB((byte) lout);
  1249.       } 
  1250.       else             /* encoded data is sliding dictionary match */
  1251.       {                
  1252.          READBIT(dict_bits,lout,(int));
  1253.          Distance = lout; 
  1254.  
  1255.          ReadTree(&distance_tree,&lout); 
  1256.          Distance |= (lout << dict_bits);
  1257.          /* using the Distance Shannon-Fano tree, read and decode the
  1258.             upper 6 bits of the Distance value */ 
  1259.  
  1260.          ReadTree(&length_tree,&Length); 
  1261.          /* using the Length Shannon-Fano tree, read and decode the
  1262.             Length value */
  1263.  
  1264.          Length += minimum_match_length; 
  1265.          if (Length == (63 + minimum_match_length)) 
  1266.          { 
  1267.             READBIT(8,lout,(int));
  1268.             Length += lout; 
  1269.          } 
  1270.  
  1271.         /* move backwards Distance+1 bytes in the output stream, and copy
  1272.           Length characters from this position to the output stream.
  1273.           (if this position is before the start of the output stream,
  1274.           then assume that all the data before the start of the output
  1275.           stream is filled with zeros) */ 
  1276.  
  1277.          op = (outpos+outcnt) - Distance - 1L;
  1278.  
  1279.           /* special case- before start of file */
  1280.           while ((op < 0L) && (Length > 0)) {
  1281.                   OUTB(0);
  1282.                   op++;
  1283.                   Length--;
  1284.           }
  1285.  
  1286.           /* normal copy of data from output buffer */
  1287.           {
  1288.                   register int ix = (int) (op % OUTBUFSIZ);
  1289.  
  1290.                   /* do a block memory copy if possible */
  1291.                   if ( ((ix    +Length) < OUTBUFSIZ) &&
  1292.                        ((outcnt+Length) < OUTBUFSIZ) ) {
  1293.                           memcpy(outptr,&outbuf[ix],Length);
  1294.                           outptr += Length;
  1295.                           outcnt += Length;
  1296.                   }
  1297.  
  1298.                   /* otherwise copy byte by byte */
  1299.                   else while (Length--) {
  1300.                           OUTB(outbuf[ix]);
  1301.                           if (++ix >= OUTBUFSIZ)
  1302.                                   ix = 0;
  1303.                   }
  1304.          }
  1305.       } 
  1306.    } 
  1307.  
  1308.  
  1309.  
  1310. /* ---------------------------------------------------------- */
  1311.  
  1312. void extract_member(VOIDARG)
  1313. {
  1314.         unsigned b;
  1315.  
  1316.     bits_left = 0;
  1317.     bitbuf = 0;
  1318.     incnt = 0;
  1319.     outpos = 0L;
  1320.     outcnt = 0;
  1321.     outptr = outbuf;
  1322.     zipeof = 0;
  1323.     crc32val = 0xFFFFFFFFL;
  1324.  
  1325.  
  1326.     /* create the output file with READ and WRITE permissions */
  1327.     if (create_output_file())
  1328.         exit(1);
  1329.  
  1330.         switch (lrec.compression_method) {
  1331.  
  1332.     case 0:        /* stored */
  1333.         {
  1334.             printf(" Extracting: %-12s ", filename);
  1335.             while (ReadByte(&b))
  1336.                 OUTB((byte) b);
  1337.         }
  1338.         break;
  1339.  
  1340.         case 1: {
  1341.             printf("UnShrinking: %-12s ", filename);
  1342.             unShrink();
  1343.         }
  1344.         break;
  1345.  
  1346.     case 2:
  1347.     case 3:
  1348.     case 4:
  1349.         case 5: {
  1350.             printf("  Expanding: %-12s ", filename);
  1351.             unReduce();
  1352.         }
  1353.         break;
  1354.  
  1355.         case 6: {
  1356.                         printf("  Exploding: %-12s ", filename);
  1357.                         unImplode();
  1358.         }
  1359.         break;
  1360.  
  1361.         default:
  1362.         printf("Unknown compression method.");
  1363.     }
  1364.  
  1365.  
  1366.     /* write the last partial buffer, if any */
  1367.     if (outcnt > 0) {
  1368.         UpdateCRC(outbuf, outcnt);
  1369.         write(outfd, outbuf, outcnt);
  1370.     }
  1371.  
  1372.     /* set output file date and time */
  1373.     set_file_time();
  1374.  
  1375.     close(outfd);
  1376.  
  1377.     crc32val = -1 - crc32val;
  1378.         if (crc32val != lrec.crc32)
  1379.                 printf(" Bad CRC %08lx  (should be %08lx)", lrec.crc32, crc32val);
  1380.  
  1381.     printf("\n");
  1382. }
  1383.  
  1384.  
  1385. /* ---------------------------------------------------------- */
  1386.  
  1387. #ifndef    OLDC
  1388. void get_string(int len, char *s)
  1389. #else
  1390. void get_string(len, s)
  1391. int len;
  1392. char *s;
  1393. #endif    /* OLDC */
  1394.  /* read a byte; return 8 if byte available, 0 if not */
  1395. {
  1396.     int len2;    /* J.E., Bug-fix for the case when string length > STRSIZ */
  1397.     len2 = len;                                     /* J.E. */
  1398.     if (len > STRSIZ) len = STRSIZ;                 /* J.E. */
  1399.     read(zipfd, s, len);
  1400.     s[len] = 0;
  1401.     lseek(zipfd, (long) (len2 - len), SEEK_CUR);    /* J.E. */
  1402. }
  1403.  
  1404.  
  1405. /* ---------------------------------------------------------- */
  1406.  
  1407. void process_local_file_header(VOIDARG)
  1408. {
  1409.     if ((long) &lrec.crc32 ==
  1410.             (long) &lrec.last_mod_file_date
  1411.             + sizeof(lrec.last_mod_file_date))
  1412.         read(zipfd, (char *) &lrec, sizeof(lrec));
  1413.     else {
  1414.         read(zipfd, (char *) &lrec, (unsigned)
  1415.             ((long) &lrec.last_mod_file_date
  1416.             + sizeof(lrec.last_mod_file_date)
  1417.             - (long) &lrec));
  1418.         read(zipfd, (char *) &lrec.crc32, (unsigned)
  1419.             ((long) &lrec.extra_field_length
  1420.             + sizeof(lrec.extra_field_length)
  1421.             - (long) &lrec.crc32));
  1422.     }
  1423.  
  1424. #ifdef HIGH_LOW
  1425.     swap_bytes(&lrec.version_needed_to_extract);
  1426.     swap_bytes(&lrec.general_purpose_bit_flag);
  1427.     swap_bytes(&lrec.compression_method);
  1428.     swap_bytes(&lrec.last_mod_file_time);
  1429.     swap_bytes(&lrec.last_mod_file_date);
  1430.     swap_lbytes(&lrec.crc32);
  1431.     swap_lbytes(&lrec.compressed_size);
  1432.     swap_lbytes(&lrec.uncompressed_size);
  1433.     swap_bytes(&lrec.filename_length);
  1434.     swap_bytes(&lrec.extra_field_length);
  1435. #endif    /* HIGH_LOW */
  1436.  
  1437.     get_string(lrec.filename_length, filename);
  1438.     get_string(lrec.extra_field_length, extra);
  1439. #ifdef    unix
  1440.     {
  1441.         char *cp;
  1442.         for (cp = filename; *cp; ++cp)
  1443.             if (isupper(*cp)) *cp = tolower(*cp);
  1444.     }
  1445. #endif    /* unix */
  1446.     extract_member();
  1447. }
  1448.  
  1449.  
  1450. /* ---------------------------------------------------------- */
  1451.  
  1452. void process_central_file_header(VOIDARG)
  1453. {
  1454.     central_directory_file_header rec;
  1455.     char filename[STRSIZ];
  1456.     char extra[STRSIZ];
  1457.     char comment[STRSIZ];
  1458.  
  1459.     if ((long) &rec.external_file_attributes ==
  1460.             (long) &rec.internal_file_attributes
  1461.             + sizeof(rec.internal_file_attributes))
  1462.         read(zipfd, (char *) &rec, sizeof(rec));
  1463.     else {
  1464.         read(zipfd, (char *) &rec, (unsigned)
  1465.             ((long) &rec.internal_file_attributes
  1466.             + sizeof(rec.internal_file_attributes)
  1467.             - (long) &rec));
  1468.         read(zipfd, (char *) &rec.external_file_attributes, (unsigned)
  1469.             ((long) &rec.relative_offset_local_header
  1470.             + sizeof(rec.relative_offset_local_header)
  1471.             - (long) &rec.external_file_attributes));
  1472.     }
  1473.  
  1474. #ifdef HIGH_LOW
  1475.     swap_bytes(&rec.version_made_by);
  1476.     swap_bytes(&rec.version_needed_to_extract);
  1477.     swap_bytes(&rec.general_purpose_bit_flag);
  1478.     swap_bytes(&rec.compression_method);
  1479.     swap_bytes(&rec.last_mod_file_time);
  1480.     swap_bytes(&rec.last_mod_file_date);
  1481.     swap_lbytes(&rec.crc32);
  1482.     swap_lbytes(&rec.compressed_size);
  1483.     swap_lbytes(&rec.uncompressed_size);
  1484.     swap_bytes(&rec.filename_length);
  1485.     swap_bytes(&rec.extra_field_length);
  1486.     swap_bytes(&rec.file_comment_length);
  1487.     swap_bytes(&rec.disk_number_start);
  1488.     swap_bytes(&rec.internal_file_attributes);
  1489.     swap_lbytes(&rec.external_file_attributes);
  1490.     swap_lbytes(&rec.relative_offset_local_header);
  1491. #endif    /* HIGH_LOW */
  1492.  
  1493.         get_string(rec.filename_length, filename);
  1494.     get_string(rec.extra_field_length, extra);
  1495.     get_string(rec.file_comment_length, comment);
  1496. #ifdef    unix
  1497.     {
  1498.         char *cp;
  1499.         for (cp = filename; *cp; ++cp)
  1500.             if (isupper(*cp)) *cp = tolower(*cp);
  1501.     }
  1502. #endif    /* unix */
  1503. }
  1504.  
  1505.  
  1506. /* ---------------------------------------------------------- */
  1507.  
  1508. void process_end_central_dir(VOIDARG)
  1509. {
  1510.     end_central_dir_record rec;
  1511.     char comment[STRSIZ];
  1512.  
  1513.     read(zipfd, (char *) &rec, sizeof(rec));
  1514.  
  1515. #ifdef HIGH_LOW
  1516.     swap_bytes(&rec.number_this_disk);
  1517. #ifndef    TURBOC
  1518.     swap_bytes(&rec.num_disk_with_start_cent_dir);
  1519.     swap_bytes(&rec.tot_ents_cent_dir_on_this_disk);
  1520. #else
  1521.     swap_bytes(&rec.number_disk_with_start_central_directory);
  1522.     swap_bytes(&rec.total_entries_central_dir_on_this_disk);
  1523. #endif    /* TURBOC */
  1524.     swap_bytes(&rec.total_entries_central_dir);
  1525.     swap_lbytes(&rec.size_central_directory);
  1526.     swap_lbytes(&rec.offset_start_central_directory);
  1527.     swap_bytes(&rec.zipfile_comment_length);
  1528. #endif    /* HIGH_LOW */
  1529.  
  1530.     get_string(rec.zipfile_comment_length, comment);
  1531. }
  1532.  
  1533.  
  1534. /* ---------------------------------------------------------- */
  1535.  
  1536. void process_headers(VOIDARG)
  1537. {
  1538.     longint sig;
  1539.  
  1540.     while (1) {
  1541.         if (read(zipfd, (char *) &sig, sizeof(sig)) != sizeof(sig))
  1542.             return;
  1543.  
  1544. #ifdef HIGH_LOW
  1545.         swap_lbytes(&sig);
  1546. #endif    /* HIGH_LOW */
  1547.  
  1548.                 if (sig == LOCAL_FILE_HEADER_SIGNATURE)
  1549.             process_local_file_header();
  1550.                 else if (sig == CENTRAL_FILE_HEADER_SIGNATURE)
  1551.             process_central_file_header();
  1552.                 else if (sig == END_CENTRAL_DIR_SIGNATURE) {
  1553.             process_end_central_dir();
  1554.             return;
  1555.         }
  1556.                 else {
  1557.             printf("Invalid Zipfile Header (0x%.8lx)\n", sig);
  1558.             return;
  1559.         }
  1560.     }
  1561.  
  1562. }
  1563.  
  1564.  
  1565. /* ---------------------------------------------------------- */
  1566.  
  1567. void extract_zipfile(VOIDARG)
  1568. {
  1569.     /*
  1570.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  1571.      * translation, which would corrupt the bitstreams 
  1572.      */
  1573.  
  1574.     if (open_input_file())
  1575.         exit(1);
  1576.  
  1577. #ifdef HIGH_LOW
  1578.     {
  1579.         word w_sig;
  1580.         longint li_sig;
  1581.         char *bp, *bp0 = (char *)&li_sig, *bp3 = ((char *)&li_sig)+3;
  1582.  
  1583.         if (read(zipfd, (char *) &w_sig, 2) == 2)
  1584.             if (w_sig == (LOCAL_FILE_HEADER_SIGNATURE & 0xffff)) {
  1585.                 w0 = 0;
  1586.                 w1 = 1;
  1587.             } else {
  1588.                 w0 = 1;
  1589.                 w1 = 0;
  1590.             }
  1591.         lseek(zipfd, 0L, SEEK_SET);
  1592.         if (read(zipfd, (char *) &li_sig, 4) == 4)
  1593.             if (li_sig == LOCAL_FILE_HEADER_SIGNATURE) {
  1594.                 li0 = 0;
  1595.                 li1 = 1;
  1596.                 li2 = 2;
  1597.                 li3 = 3;
  1598.             } else {
  1599.                 li0 = li1 = li2 = li3 = 0;
  1600.                 for (bp = bp0; bp < bp3; ++bp, ++li0)
  1601.                     if (*bp < 0x4b && !(*bp & 0x01))
  1602.                         break;
  1603.                 for (bp = bp0; bp < bp3; ++bp, ++li1)
  1604.                     if (*bp < 0x4b && (*bp & 0x01))
  1605.                         break;
  1606.                 for (bp = bp0; bp < bp3; ++bp, ++li2)
  1607.                     if (*bp == ((LOCAL_FILE_HEADER_SIGNATURE
  1608.                             >> 8) & 0xffL))
  1609.                         break;
  1610.                 for (bp = bp0; bp < bp3; ++bp, ++li3)
  1611.                     if (*bp == (LOCAL_FILE_HEADER_SIGNATURE
  1612.                             & 0xffL))
  1613.                         break;
  1614.             }
  1615.         lseek(zipfd, 0L, SEEK_SET);
  1616.     }
  1617. #endif    /* HIGH_LOW */
  1618.  
  1619.     process_headers();
  1620.  
  1621.     close(zipfd);
  1622. }
  1623.  
  1624.  
  1625. /* ---------------------------------------------------------- */
  1626. /*
  1627.  * main program
  1628.  *
  1629.  */
  1630.  
  1631. #ifndef    OLDC
  1632. void main(int argc, char **argv)
  1633. #else
  1634. void main(argc, argv)
  1635. int argc;
  1636. char **argv;
  1637. #endif    /* OLDC */
  1638.  /* read a byte; return 8 if byte available, 0 if not */
  1639. {
  1640.     MacInit(&argc, argv);    /* J.E., Provide command line arguments */
  1641.     if (argc != 2) {
  1642.                 printf("\n%s\nCourtesy of:  S.H.Smith  and  The Tool Shop BBS,  (602) 279-2673.\n\n",VERSION);
  1643.         printf("You may copy and distribute this program freely, provided that:\n");
  1644.         printf("    1)   No fee is charged for such copying and distribution, and\n");
  1645.         printf("    2)   It is distributed ONLY in its original, unmodified state.\n\n");
  1646.         printf("If you wish to distribute a modified version of this program, you MUST\n");
  1647.         printf("include the source code.\n\n");
  1648.         printf("If you modify this program, I would appreciate a copy of the  new source\n");
  1649.         printf("code.   I am holding the copyright on the source code, so please don't\n");
  1650.         printf("delete my name from the program files or from the documentation.\n\n");
  1651.                 printf("IN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST\n");
  1652.                 printf("PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES\n");
  1653.                 printf("ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY\n");
  1654.                 printf("CLAIM BY ANY OTHER PARTY.\n\n");
  1655.                 printf("Usage:  UnZip FILE[.zip]\n");
  1656.                 exit(1);
  1657.     }
  1658.  
  1659.     /* .ZIP default if none provided by user */
  1660.     strcpy(zipfn, argv[1]);
  1661.     if (strchr(zipfn, '.') == NULL)
  1662.         strcat(zipfn, ".zip");
  1663.  
  1664.         /* allocate i/o buffers */
  1665.     inbuf = (byte *) (malloc(INBUFSIZ));
  1666.     outbuf = (byte *) (malloc(OUTBUFSIZ));
  1667.     if ((inbuf == NULL) || (outbuf == NULL)) {
  1668.         printf("Can't allocate buffers!\n");
  1669.         exit(1);
  1670.     }
  1671.  
  1672.         /* do the job... */
  1673.         extract_zipfile();
  1674.     exit(0);
  1675. }
  1676.  
  1677. #include "MacUnZip.c"    /* J.E., Append special code for the Macintosh */